/* $Id: NonClientCompanyRegisterFacadeImpl.java 
 * Copyright (C) 2011, TRAKHEES
 *  
 * Revision History
 *
 * Date  			Author 		    	Remarks
 * ---------------------------------------------------------------------------------
 *
 */
package ae.pcfc.etks.online.common.facade.provider;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.springframework.transaction.annotation.Transactional;

import ae.pcfc.etks.online.common.ConstantsCommon;
import ae.pcfc.etks.online.common.ConstantsCommon.WorkflowDepartment;
import ae.pcfc.etks.online.common.domain.AppMetaData;
import ae.pcfc.etks.online.common.domain.ClientCompanyReq;
import ae.pcfc.etks.online.common.domain.ProcStepAthmnt;
import ae.pcfc.etks.online.common.domain.TTscClientCategory;
import ae.pcfc.etks.online.common.domain.TTscClientRoleToDepartmentMap;
import ae.pcfc.etks.online.common.domain.TTscDepartments;
import ae.pcfc.etks.online.common.domain.manager.AppMetaDataDomainObjectManager;
import ae.pcfc.etks.online.common.domain.manager.AttachmentTypeDomainObjectManager;
import ae.pcfc.etks.online.common.domain.manager.NonClientCompanyDomainObjectManager;
import ae.pcfc.etks.online.common.domain.manager.NonClientPersonDomainObjectManager;
import ae.pcfc.etks.online.common.domain.manager.ProcessDomainObjectManager;
import ae.pcfc.etks.online.common.domain.manager.SingleClientCompanyDomainObjectManager;
import ae.pcfc.etks.online.common.domain.manager.UtilityDomainObjectManager;
import ae.pcfc.etks.online.common.exception.DuplicateClientEmailException;
import ae.pcfc.etks.online.common.exception.DuplicateClientLicenseException;
import ae.pcfc.etks.online.common.exception.DuplicateClientNameException;
import ae.pcfc.etks.online.common.facade.NonClientCompanyRegisterFacade;
import ae.pcfc.etks.online.common.vo.ClientCategoryVO;
import ae.pcfc.etks.online.common.vo.ClientNameVO;
import ae.pcfc.etks.online.common.vo.LicenseVO;
import ae.pcfc.etks.online.common.vo.NonClientCompanyVO;
import ae.pcfc.etks.online.common.vo.TrakheesIdAndPINVO;
import ae.pcfc.etks.online.common.vo.UploadDocumentVO;
import ae.pcfc.etks.online.wf.service.client.NonClientWF;
import ae.pcfc.etks.online.wf.service.client.vo.LaunchIncidentVO;

public class NonClientCompanyRegisterFacadeImpl extends BaseFacade implements
		NonClientCompanyRegisterFacade {
    	/*
	 * Here we coordinate between the all interacting business domain objects
	 * (BO), transactions are maintained here. use case business validation are
	 * maintained here (that requires DB checks or retrieving data from DB)
	 */
	private NonClientCompanyDomainObjectManager nonClientCompanyDomainObjectManager;
	private ProcessDomainObjectManager processDomainObjectManager;
	private AppMetaDataDomainObjectManager appMetaDataDomainObjectManager;
	private AttachmentTypeDomainObjectManager attachmentTypeDomainObjectManager;
	private NonClientWF nonClientCompanyWF;
	private SingleClientCompanyDomainObjectManager singleClientCompanyDomainObjectManager;

	private UtilityDomainObjectManager utilityDomainObjectManager;
	private NonClientPersonDomainObjectManager nonClientPersonDomainObjectManager;

	public NonClientPersonDomainObjectManager getNonClientPersonDomainObjectManager() {
	    return nonClientPersonDomainObjectManager;
	}

	public void setNonClientPersonDomainObjectManager(
		NonClientPersonDomainObjectManager nonClientPersonDomainObjectManager) {
	    this.nonClientPersonDomainObjectManager = nonClientPersonDomainObjectManager;
	}

	public NonClientCompanyDomainObjectManager getNonClientCompanyDomainObjectManager() {
	    return nonClientCompanyDomainObjectManager;
	}
	/**
	 * setNonClientCompanyDomainObjectManager
	 * 
	 * @param nonClientCompanyDomainObjectManager
	 * void
	 */
	public void setNonClientCompanyDomainObjectManager(
			NonClientCompanyDomainObjectManager nonClientCompanyDomainObjectManager) {
		this.nonClientCompanyDomainObjectManager = nonClientCompanyDomainObjectManager;
	}

	/**
	 * setProcessDomainObjectManager
	 * 
	 * @param processDomainObjectManager
	 * void
	 */
	public void setProcessDomainObjectManager(
			ProcessDomainObjectManager processDomainObjectManager) {
		this.processDomainObjectManager = processDomainObjectManager;
	}

	/**
	 * getUtilityDomainObjectManager
	 * 
	 * @return
	 * UtilityDomainObjectManager
	 */
	public UtilityDomainObjectManager getUtilityDomainObjectManager() {
		return utilityDomainObjectManager;
	}

	/**
	 * setUtilityDomainObjectManager
	 * 
	 * @param utilityDomainObjectManager
	 * void
	 */
	public void setUtilityDomainObjectManager(
			UtilityDomainObjectManager utilityDomainObjectManager) {
		this.utilityDomainObjectManager = utilityDomainObjectManager;
	}

	/**
	 * setAppMetaDataDomainObjectManager
	 * 
	 * @param appMetaDataDomainObjectManager
	 * void
	 */
	public void setAppMetaDataDomainObjectManager(
			AppMetaDataDomainObjectManager appMetaDataDomainObjectManager) {
		this.appMetaDataDomainObjectManager = appMetaDataDomainObjectManager;
	}

	/**
	 * setAttachmentTypeDomainObjectManager
	 * 
	 * @param attachmentTypeDomainObjectManager
	 * void
	 */
	public void setAttachmentTypeDomainObjectManager(
			AttachmentTypeDomainObjectManager attachmentTypeDomainObjectManager) {
		this.attachmentTypeDomainObjectManager = attachmentTypeDomainObjectManager;
	}

	/**
	 * setNonClientCompanyWF
	 * 
	 * @param nonClientCompanyWF
	 * void
	 */
	public void setNonClientCompanyWF(NonClientWF nonClientCompanyWF) {
		this.nonClientCompanyWF = nonClientCompanyWF;
	}

	/**
	 * setSingleClientCompanyDomainObjectManager
	 * 
	 * @param singleClientCompanyDomainObjectManager
	 * void
	 */
	public void setSingleClientCompanyDomainObjectManager(
			SingleClientCompanyDomainObjectManager singleClientCompanyDomainObjectManager) {
		this.singleClientCompanyDomainObjectManager = singleClientCompanyDomainObjectManager;
	}

	/**
	 * registerNonClientCompany
	 * 
	 * @see ae.pcfc.etks.online.common.facade.NonClientCompanyRegisterFacade#registerNonClientCompany(ae.pcfc.etks.online.common.vo.NonClientCompanyVO)
	 * 
	 */
	@Transactional
	public String registerNonClientCompany(NonClientCompanyVO nonClientCompanyVO) {

		//if (validateNonClientCompanyReq(nonClientCompanyVO)) {
			AppMetaData appMetaData = new AppMetaData();

			ae.pcfc.etks.online.common.domain.Process process = processDomainObjectManager.getProcessByProcessAndStepCode(
							nonClientCompanyVO.getProcessCode().getProcessCode(),
							nonClientCompanyVO.getStrProcessStep());
			appMetaData.setProcess(process);
			getMapper().map(nonClientCompanyVO, appMetaData);

			/***
			 * Mapper is not used because we have to set the attachment types
			 * which are in the nested entity
			 ***/
			Set<ProcStepAthmnt> procStepAtmnt = new HashSet<ProcStepAthmnt>();
			List<UploadDocumentVO> documentVOs = nonClientCompanyVO
					.getArrDocumentVOs();
			ProcStepAthmnt athmnt;

			for (UploadDocumentVO documentVO : documentVOs) {
				athmnt = new ProcStepAthmnt();
				athmnt.setAppMetaData(appMetaData);
				athmnt.setProcessStep(process.getProcessSteps().iterator().next());
				athmnt.setAttachmentPath(documentVO.getURL());
				athmnt.setAttachmentType(attachmentTypeDomainObjectManager.getAttachmentTypeByAttachmentCode(
							documentVO.getStrUploadDocumentType()));
				procStepAtmnt.add(athmnt);
			}

			if (procStepAtmnt.size() > 0)
				appMetaData.setProcStepAthmnts(procStepAtmnt);


			appMetaDataDomainObjectManager.add(appMetaData);

			ClientCompanyReq clientCompanyReq = new ClientCompanyReq();

			getMapper().map(nonClientCompanyVO, clientCompanyReq);

			clientCompanyReq.setApplicationId(appMetaData.getApplicationId());
			nonClientCompanyDomainObjectManager.add(clientCompanyReq);

			return appMetaData.getClientRefNo();
		/*} else
			return null;*/

	}

	/**
	 * validateNonClientCompanyReq
	 * 
	 * @param nonClientCompanyVO
	 * @return
	 * boolean
	 */
	@Transactional(readOnly = true)
	public boolean validateNonClientCompanyReq(
			NonClientCompanyVO nonClientCompanyVO) {

		LicenseVO licenseVO = new LicenseVO();
		getMapper().map(nonClientCompanyVO, licenseVO);

		// Checking if the License no already exist against the same license
		// issuing authority
		if (this.singleClientCompanyDomainObjectManager
				.validateLicense(licenseVO)
				&& this.nonClientCompanyDomainObjectManager
						.validateLicenseReq(licenseVO)){
			TrakheesIdAndPINVO trakheesIdAndPINVO = this.singleClientCompanyDomainObjectManager
					.findTrakheesIdAndPinByEmail(nonClientCompanyVO
							.getStrEmailAddress());

			if (trakheesIdAndPINVO != null) {
				throw new DuplicateClientEmailException(
						nonClientCompanyVO.getStrEmailAddress());
			}

			ClientNameVO clientNameEngVO = new ClientNameVO();
			clientNameEngVO.setStrNameEng(nonClientCompanyVO
					.getStrCompNameEng());
			boolean validNameEng = this.singleClientCompanyDomainObjectManager
					.validateClientName(clientNameEngVO);

			if (!validNameEng)
				throw new DuplicateClientNameException(
						nonClientCompanyVO.getStrCompNameEng());

			ClientNameVO clientNameArbVO = new ClientNameVO();
			clientNameArbVO.setStrNameArb(nonClientCompanyVO
					.getStrCompNameArab());
			boolean validNameArb = this.singleClientCompanyDomainObjectManager
					.validateClientName(clientNameArbVO);

			if (!validNameArb)
				throw new DuplicateClientNameException(
						nonClientCompanyVO.getStrCompNameArab());

			if (this.nonClientCompanyDomainObjectManager
					.validateByPropertyName("ccNameEng",
							nonClientCompanyVO.getStrCompNameEng())) {
				if (this.nonClientCompanyDomainObjectManager
						.validateByPropertyName("ccNameArb",
								nonClientCompanyVO.getStrCompNameArab())) {
					if (this.nonClientCompanyDomainObjectManager.validateByPropertyName("ccEmail",nonClientCompanyVO.getStrEmailAddress())
					&&this.nonClientPersonDomainObjectManager.validateByPropertyName("cpEmail",nonClientCompanyVO.getStrEmailAddress())) {
						// return true;
					} else {
						throw new DuplicateClientEmailException(
								nonClientCompanyVO.getStrEmailAddress());
					}
				} else {
					throw new DuplicateClientNameException(
							nonClientCompanyVO.getStrCompNameArab());
				}
			} else {
				throw new DuplicateClientNameException(
						nonClientCompanyVO.getStrCompNameEng());
			}
		} else
			throw new DuplicateClientLicenseException(
					nonClientCompanyVO.getStrLicenseNumber(),
					nonClientCompanyVO.getStrLicenseIssuingAuth());

		return true;

		// LicenseVO licenseVO = new LicenseVO();
		// boolean bRejectedClient = false;
		// getMapper().map(nonClientCompanyVO, licenseVO);
		//
		// // Checking if the License no already exist against the same license
		// // issuing authority
		// if
		// (this.singleClientCompanyDomainObjectManager.validateLicense(licenseVO)
		// &&
		// this.nonClientCompanyDomainObjectManager.validateLicenseReq(licenseVO))
		//
		// {
		// TrakheesIdAndPINVO trakheesIdAndPINVO =
		// this.singleClientCompanyDomainObjectManager
		// .findTrakheesIdAndPinByEmail(nonClientCompanyVO.getStrEmailAddress());
		//
		// ClientCompanyReq clientCompanyReqest =
		// this.nonClientCompanyDomainObjectManager
		// .getNonClientCompanyByEmail(nonClientCompanyVO.getStrEmailAddress());
		//
		// // if the email is already in the system or rejected
		// if (trakheesIdAndPINVO != null || clientCompanyReqest != null)
		//
		// if(clientCompanyReqest != null && clientCompanyReqest.getCcStatus()
		// != null &&
		// (!clientCompanyReqest.getCcStatus().equals(ConstantsCommon.REJECT)))
		//
		// throw new
		// DuplicateClientEmailException(nonClientCompanyVO.getStrEmailAddress());
		//
		// if(clientCompanyReqest != null && clientCompanyReqest.getCcStatus()
		// != null &&
		// (clientCompanyReqest.getCcStatus().equals(ConstantsCommon.REJECT))){
		// bRejectedClient = true;
		// }
		//
		// if
		// (this.nonClientPersonDomainObjectManager.findByPropertyName("cpEmail",
		// nonClientCompanyVO.getStrEmailAddress()) == null) {
		//
		// } else {
		// throw new
		// DuplicateClientEmailException(nonClientCompanyVO.getStrEmailAddress());
		// }
		// } else
		// throw new
		// DuplicateClientLicenseException(nonClientCompanyVO.getStrLicenseNumber(),
		// nonClientCompanyVO.getStrLicenseIssuingAuth());
		//
		// ClientCompanyReq clientCompanyReq =
		// this.nonClientCompanyDomainObjectManager.getNonClientCompanyByPropertyName(
		// "ccNameEng", nonClientCompanyVO.getStrCompNameEng());
		//
		// if (clientCompanyReq != null && clientCompanyReq.getCcStatus() !=
		// null &&
		// (!clientCompanyReq.getCcStatus().equals(ConstantsCommon.REJECT)))
		// throw new
		// DuplicateClientNameException(nonClientCompanyVO.getStrCompNameEng());
		//
		// ClientCompanyReq clientCompanyReq2 =
		// this.nonClientCompanyDomainObjectManager.getNonClientCompanyByPropertyName(
		// "ccNameArb", nonClientCompanyVO.getStrCompNameArab());
		//
		// if (clientCompanyReq2 != null && clientCompanyReq2.getCcStatus() !=
		// null &&
		// (!clientCompanyReq2.getCcStatus().equals(ConstantsCommon.REJECT)))
		// throw new
		// DuplicateClientNameException(nonClientCompanyVO.getStrCompNameArab());
		//
		// ClientNameVO clientNameEngVO = new ClientNameVO();
		// clientNameEngVO.setStrNameEng(nonClientCompanyVO.getStrCompNameEng());
		// boolean validNameEng =
		// this.singleClientCompanyDomainObjectManager.validateClientName(clientNameEngVO);
		//
		// if (!validNameEng)
		// throw new
		// DuplicateClientNameException(nonClientCompanyVO.getStrCompNameEng());
		//
		// ClientNameVO clientNameArbVO = new ClientNameVO();
		// clientNameArbVO.setStrNameArb(nonClientCompanyVO.getStrCompNameArab());
		// boolean validNameArb =
		// this.singleClientCompanyDomainObjectManager.validateClientName(clientNameArbVO);
		//
		// if (!validNameArb)
		// throw new
		// DuplicateClientNameException(nonClientCompanyVO.getStrCompNameArab());
		//
		// return true;
	}

	/**
	 * getClientCategory
	 * 
	 * @see ae.pcfc.etks.online.common.facade.NonClientCompanyRegisterFacade#getClientCategory(java.lang.String)
	 * 
	 */
	@Transactional(readOnly = true)
	public List<ClientCategoryVO> getClientCategory(String clientType) {

		List<TTscClientCategory> clientCategories = this.singleClientCompanyDomainObjectManager
				.getClientCategory(clientType);

		List<ClientCategoryVO> clientCategoryVos = new ArrayList<ClientCategoryVO>(
				0);

		for (TTscClientCategory clientCategory : clientCategories) {

			ClientCategoryVO clientCategoryVO = new ClientCategoryVO();

			getMapper().map(clientCategory, clientCategoryVO);

			clientCategoryVos.add(clientCategoryVO);

		}

		return clientCategoryVos.size() > 0 ? clientCategoryVos : null;
	}
	/**
	 * updateWorkflowIncidentVO
	 * Method to set the departments which should act on the workflow request in the Workflow request Object(LaunchIncidentVO)
	 * @param launchIncidVO
	 * @param iClientRole
	 * void
	 */
	@Transactional(readOnly = true)
	public void updateWorkflowIncidentVO(LaunchIncidentVO launchIncidVO, List<Integer> iClientRole){
		if(launchIncidVO != null && iClientRole != null ){
			List<String> strClientRoles = new ArrayList<String>();
			for(Integer roleId : iClientRole){
				strClientRoles.add(roleId.toString());
			}
			List<TTscClientRoleToDepartmentMap> departments = this.utilityDomainObjectManager.getDepartmentsByRoleIds(strClientRoles);
			if( departments == null ){
				departments = new ArrayList<TTscClientRoleToDepartmentMap>();
			}
			
			List<String> strDepartments = new ArrayList<String>();
			List<WorkflowDepartment> wfDepartments = new ArrayList<WorkflowDepartment>();
			for(TTscClientRoleToDepartmentMap deptMap : departments){
				TTscDepartments dept = deptMap.getDepartment();
				strDepartments.add(dept.getDeptCode().toUpperCase());
				wfDepartments.add(WorkflowDepartment.getWorkflowDepartmentfromString(dept.getDeptCode()));
			}
			launchIncidVO.setgApprovalFIN(ConstantsCommon.SET_VALUE);
			if(strDepartments.contains(WorkflowDepartment.CED.getCode())){
				launchIncidVO.setgApprovalCED(ConstantsCommon.SET_VALUE);
			}else{
				launchIncidVO.setgApprovalCED(ConstantsCommon.UNSET_VALUE);
			}
			if(strDepartments.contains(WorkflowDepartment.CLD.getCode())){
				launchIncidVO.setgApprovalCLD(ConstantsCommon.SET_VALUE);
			}else{
				launchIncidVO.setgApprovalCLD(ConstantsCommon.UNSET_VALUE);
			}
			if(strDepartments.contains(WorkflowDepartment.EHS.getCode())){
				launchIncidVO.setgApprovalEHS(ConstantsCommon.SET_VALUE);
			}else{
				launchIncidVO.setgApprovalEHS(ConstantsCommon.UNSET_VALUE);
			}
		}
	}
}
